<?php
/**
 * Nweb Framework
 *
 * This script is protected by copyright. It's use, copying, modification
 * and distribution without written consent of the author is prohibited.
 *
 * @category    source
 * @package     pl.nweb.framework.log
 * @author      Krzysztof Kardasz <krzysztof.kardasz@gmail.com>
 * @copyright   Copyright (c) 2011 Krzysztof Kardasz
 * @license     http://www.gnu.org/licenses/lgpl-3.0.txt  GNU Lesser General Public
 * @version     3.0 $Id: stream.php 435 2011-09-23 13:24:30Z krzysztof.kardasz $
 * @link        http://code.google.com/p/nweb-framework/
 * @link        http://framework.nweb.pl
 */

namespace pl\nweb\framework\log;

/**
 * Dziennik zdarzeń
 *
 * @category    source
 * @package     pl.nweb.framework.log
 * @author      Krzysztof Kardasz <krzysztof.kardasz@gmail.com>
 * @copyright   Copyright (c) 2011 Krzysztof Kardasz
 * @version     3.0 $Id: stream.php 435 2011-09-23 13:24:30Z krzysztof.kardasz $
 */
class Stream extends \pl\nweb\framework\Log
{
    /**
     * Strumień, uchwyt
     *
     * @var null|resorce
     */
    private $_handle = null;

    /**
     * Strumień
     *
     * @var null|resorce|string
     */
    private $_stream = null;

    /**
     * Tryb zapisu
     *
     * @var string
     */
    private $_mode = null;

    /**
     * Domyślny tryb
     */
    const DEFAULT_MODE = 'a';

    /**
     * Opcja, strumień
     */
    const OPTION_STREAM = 'stream';

    /**
     * Opcja, tryb zapisu
     */
    const OPTION_MODE = 'mode';

    /**
     * Konstruktor
     *
     * @param array $options konfiguracja
     */
    public function __construct (array $options = array())
    {
        parent::__construct($options);

        if(isset($options[self::OPTION_MODE])) {
            $this->setMode($options[self::OPTION_MODE]);
        }

        if(isset($options[self::OPTION_STREAM])) {
            $this->setStream($options[self::OPTION_STREAM]);
        }
    }

    /**
     * Definiowanie katalogu dla plików cache
     *
     * @param  string|resource $stream strumień
     * @return \pl\nweb\framework\log\Stream
     * @throws Exception
     */
    public function setStream ($stream)
    {
        if(is_resource($stream)) {
            if (get_resource_type($stream) != 'stream') {
                throw new Exception ('Error, resource is not stream!');
            }
        }

        $this->_stream = (string)$stream;
        return $this;
    }

    /**
     * Zwraca strumień
     *
     * @return string|resource
     */
    public function getStream ()
    {
        if(null === $this->_stream) {
            $this->setStream ('php://output');
        }
        return $this->_stream;
    }

    /**
     * Definiowanie trybu
     *
     * @param  string $mode tryb
     * @return \pl\nweb\framework\log\Stream
     */
    public function setMode ($mode)
    {
        $this->_mode = $mode;
        return $this;
    }

    /**
     * Zwraca tryb
     *
     * @return string
     */
    public function getMode ()
    {
        return $this->_mode;
    }

    /**
     * Zwraca strumień zasobu
     *
     * @return resource
     */
    private function _stream ()
    {
        if(null === $this->_handle) {
            if(is_resource($this->getStream())) {
                if(null !== $this->getMode()) {
                    throw new Exception ('Cannot change stream mode if is opened');
                }
                $this->_handle = $this->getStream();
            } else {
                $this->_handle = @fopen($this->getStream(), ((null === $this->getMode()) ? self::DEFAULT_MODE : $this->getMode()), false);
            }
            if(!$this->_handle) {
                throw new Exception ('Cannot open stream');
            }
        }

        return $this->_handle;
    }

    /**
     * Wpis do dziennika
     *
     * @param  string $message wiadomość
     * @param  integer $level kategoria
     * @param  array $options konfiguracja
     * @return boolean
     */
    public function log ($message, $level = self::LEVEL_INFO, array $options = array())
    {
        if(!$this->isEnabled()) {
            return;
        }

        $line = implode("\t", array(
            '[' . $this->getLevel($level) . ']',
            date('Y-m-d H:i:s'),
            $message,
        )) . "\n";

        if (false === @fwrite($this->_stream (), $line)) {
            throw new Exception('Unable to write to stream');
        }
        return true;
    }
}